package org.grc.app.z_project.z_framework.proxy;

import java.lang.reflect.Method;

import org.grc.app.z_project.z_framework.annotation.Transaction;
import org.grc.app.z_project.z_framework.helper.DataBaseHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 事务代理切面类
 * 
 * @author grc
 * @since 1.0-SNAPSHOT
 */
public class TransactionProxy implements Proxy {

	private static final Logger LOGGER = LoggerFactory.getLogger(TransactionProxy.class);
	
	// 保证同一线程中事务控制逻辑只执行一次
	private static final ThreadLocal<Boolean> FLAG_HOLDER = new ThreadLocal<Boolean>() {
		@Override
		protected Boolean initialValue() {
			return Boolean.FALSE;
		};
	}; 
	
	@Override
	public Object doProxy(ProxyChain proxyChain) throws Throwable {
		Object result = null;
		boolean flag = FLAG_HOLDER.get();
		Method method = proxyChain.getTargetMethod();
		if (!flag && method.isAnnotationPresent(Transaction.class)) {
			FLAG_HOLDER.set(true);
			try {
				DataBaseHelper.beginTransaction();
				LOGGER.debug("begin transaction");
				result = proxyChain.doProxyChain();
				DataBaseHelper.commitTransaction();
				LOGGER.debug("commit transaction");
			} catch (Exception e) {
				DataBaseHelper.rollbackTransaction();
				LOGGER.debug("roll back transaction");
				throw e;
			} finally {
				FLAG_HOLDER.remove();
			}
		} else {
			result = proxyChain.doProxyChain();
		}
		return result;
	}
}
